/*
 * @Author: Wangjun
 * @Date: 2023-08-16 18:45:07X6Port
 * @LastEditTime: 2023-10-27 11:28:54
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \xr_node_calcd:\go\src\gitee.com\hnxr_1\nodex\x6_2_task.go
 * hnxr
 */
package nodex

import (
	"fmt"
	"sort"
)

// Task 业务画布
type Task struct {
	Category string  //业务类型
	Cells    []*Cell `json:"cells"`
	FileName string  `json:"filename"`
	Attrib   string  `json:"attrib"`
	Err      error
}

func (m *Task) ToNodes() (nodes []Noder, edges []*Edge, err error) {
	mapPort := make(map[string]Valuer) //id 对应的端口
	for _, cell := range m.Cells {
		if cell.ID == "" {
			continue
		}
		switch cell.Shape {
		case "edge":
			if cell.Source == nil {
				continue
			}
			if cell.Target == nil {
				continue
			}
			if cell.Source.Cell == "" || cell.Source.Port == "" {
				continue
			}
			if cell.Target.Cell == "" || cell.Target.Port == "" {
				continue
			}

			edge := new(Edge)
			edge.ID = cell.ID
			edge.Source = *cell.Source
			edge.Target = *cell.Target
			edges = append(edges, edge)
		case "op-rect", "op-rect-io":
			data := cell.Data
			if data == nil {
				continue
			}
			if cell.Ports == nil {
				continue
			}

			// "model": "逻辑运算",
			// "modelId": "3",
			// "name": "比较运算",
			// "sysmbol": "CMP"
			node := New(data.Sysmbol, cell.ID)
			if node == nil {
				err = fmt.Errorf("不存在的算子[%s:%s]", cell.ID, data.Sysmbol)
				return nil, nil, err
			}
			node.SetSN(data.SN)
			node.SetExtends(data.Extends)
			node.SetEnQ(data.EnQ)
			for _, item := range cell.Ports.Items {
				if item.Data == nil {
					continue
				}
				//log.Printf("[%s:%s,%s]", data.Sysmbol, item.ID, item.Data.Name)
				param, err := node.GetParam(item.Data.Name)
				if err != nil {
					err = fmt.Errorf("无效的参数[%s:%s,%s:%s]", data.Sysmbol, item.ID, item.Data.Name, err.Error())
					return nil, nil, err
				}
				param.SetID(item.ID)
				err = param.SetValue(item.Data.SV)
				if err != nil {
					err = fmt.Errorf("无效的参数[%s:%s,%s:%s]", data.Sysmbol, item.ID, item.Data.Name, err.Error())
					return nil, nil, err
				}
				mapPort[item.ID] = param
			}
			nodes = append(nodes, node)
		}
	}

	//查找连线对应的端点
	for _, edge := range edges {
		out := mapPort[edge.Source.Port]
		if out == nil {
			err = fmt.Errorf("找不到输出参数[%s]", edge.Source.Port)
			return
		}
		in := mapPort[edge.Target.Port]
		if in == nil {
			err = fmt.Errorf("找不到输入参数[%s]", edge.Target.Port)
			return
		}

		in.SetEdge(edge.ID)
		in.SetPrevPort(edge.Source.Port)
		err = out.Link(in)
		if err != nil {
			err = fmt.Errorf("数据关联错误[%s->%s]", edge.Source.Port, edge.Target.Port)
			return
		}
	}

	sort.Slice(nodes, func(i, j int) bool {
		return nodes[i].GetSN() < nodes[j].GetSN()
	})
	return
}

type Cell struct {
	ID     string    `json:"id"`
	Data   *X6Data   `json:"data"`
	Ports  *X6Port   `json:"ports"`
	Shape  string    `json:"shape"`
	Source *EdgePort `json:"source"`
	Target *EdgePort `json:"target"`
}

type X6Port struct {
	Items []*X6Item `jons:"items"`
}

type X6Item struct {
	Data *X6PortData `json:"data"`
	ID   string      `json:"id"`
}

type X6PortData struct {
	// "dataType": "Boolean",
	// "desc": "输入值X",
	// "kind": "in",
	// "name": "X"
	Name     string `json:"name"`
	DataType string `json:"dataType"`
	SV       any    `json:"sv"` //SetValue 设定值
}

type X6Data struct {
	Model    string         `json:"model"`
	ModuleID string         `json:"modelId"`
	Name     string         `json:"name"`
	Sysmbol  string         `json:"sysmbol"`
	SN       int            `json:"sn"`
	EnQ      bool           `json:"isEnabled"` //禁用质量检查
	Extends  map[string]any `json:"extends"`   //其他数据
}
